package org.springblade.common.tool;


import java.math.BigInteger;
import java.security.SecureRandom;
import java.security.Security;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

public class SM2Util {
	private static final ECDomainParameters DOMAIN_PARAMS;

	public SM2Util() {
	}

	public static AsymmetricCipherKeyPair generateKeyPair() {
		ECKeyPairGenerator generator = new ECKeyPairGenerator();
		generator.init(new ECKeyGenerationParameters(DOMAIN_PARAMS, new SecureRandom()));
		return generator.generateKeyPair();
	}

	public static byte[] encrypt(String input, String publicKey) {
		return encrypt(input, stringToPublicKey(publicKey));
	}

	public static byte[] encrypt(String input, ECPublicKeyParameters publicKey) {
		try {
			SM2Engine engine = new SM2Engine();
			engine.init(true, new ParametersWithRandom(publicKey, new SecureRandom()));
			byte[] inputBytes = input.getBytes();
			return engine.processBlock(inputBytes, 0, inputBytes.length);
		} catch (Exception var4) {
			return null;
		}
	}

	public static String decrypt(String encrypted, String privateKey) {
		return decrypt(Hex.decode(encrypted), privateKey);
	}

	public static String decrypt(byte[] encrypted, String privateKey) {
		return decrypt(encrypted, stringToPrivateKey(privateKey));
	}

	public static String decrypt(byte[] encrypted, ECPrivateKeyParameters privateKey) {
		try {
			SM2Engine engine = new SM2Engine();
			engine.init(false, privateKey);
			byte[] decryptedBytes = engine.processBlock(encrypted, 0, encrypted.length);
			return new String(decryptedBytes);
		} catch (Exception var4) {
			return null;
		}
	}

	public static byte[] sign(String input, String privateKey) {
		return sign(input, stringToPrivateKey(privateKey));
	}

	public static byte[] sign(String input, ECPrivateKeyParameters privateKey) {
		try {
			SM2Signer signer = new SM2Signer();
			signer.init(true, new ParametersWithRandom(privateKey, new SecureRandom()));
			byte[] inputBytes = input.getBytes();
			signer.update(inputBytes, 0, inputBytes.length);
			return signer.generateSignature();
		} catch (Exception var4) {
			return null;
		}
	}

	public static boolean verify(String input, byte[] signature, String publicKey) {
		return verify(input, signature, stringToPublicKey(publicKey));
	}

	public static boolean verify(String input, byte[] signature, ECPublicKeyParameters publicKey) {
		try {
			SM2Signer signer = new SM2Signer();
			signer.init(false, publicKey);
			byte[] inputBytes = input.getBytes();
			signer.update(inputBytes, 0, inputBytes.length);
			return signer.verifySignature(signature);
		} catch (Exception var5) {
			return false;
		}
	}

	public static String getPublicKeyString(AsymmetricCipherKeyPair keyPair) {
		ECPublicKeyParameters ecPublicKeyParameters = (ECPublicKeyParameters)keyPair.getPublic();
		return Hex.toHexString(ecPublicKeyParameters.getQ().getEncoded(false));
	}

	public static String getPrivateKeyString(AsymmetricCipherKeyPair keyPair) {
		ECPrivateKeyParameters ecPrivateKeyParameters = (ECPrivateKeyParameters)keyPair.getPrivate();
		return Hex.toHexString(ecPrivateKeyParameters.getD().toByteArray());
	}

	public static ECPublicKeyParameters stringToPublicKey(String data) {
		return new ECPublicKeyParameters(DOMAIN_PARAMS.getCurve().decodePoint(Hex.decode(data)), DOMAIN_PARAMS);
	}

	public static ECPrivateKeyParameters stringToPrivateKey(String data) {
		return new ECPrivateKeyParameters(new BigInteger(Hex.decode(data)), DOMAIN_PARAMS);
	}

	static {
		Security.addProvider(new BouncyCastleProvider());
		X9ECParameters spec = GMNamedCurves.getByName("sm2p256v1");
		DOMAIN_PARAMS = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN(), spec.getH());
	}
}
